using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace Sunny.UI;

internal static class TransExp<TIn, TOut>
{
	private static readonly Func<TIn, TOut> cache = GetFunc();

	private static Func<TIn, TOut> GetFunc()
	{
		ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
		List<MemberBinding> list = new List<MemberBinding>();
		PropertyInfo[] properties = typeof(TOut).GetProperties();
		foreach (PropertyInfo propertyInfo in properties)
		{
			if (propertyInfo.CanWrite)
			{
				MemberExpression expression = Expression.Property(parameterExpression, typeof(TIn).GetProperty(propertyInfo.Name));
				MemberBinding item = Expression.Bind(propertyInfo, expression);
				list.Add(item);
			}
		}
		return Expression.Lambda<Func<TIn, TOut>>(Expression.MemberInit(Expression.New(typeof(TOut)), list.ToArray()), new ParameterExpression[1] { parameterExpression }).Compile();
	}

	public static TOut Trans(TIn tIn)
	{
		return cache(tIn);
	}
}
